package com.snmp.smn.agent;

import java.io.File;
import java.io.FileInputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Properties;

import com.snmp.smn.monitors.ShutdownMonitor;
import com.snmp.smn.pdu.PDUFactory;
import com.snmp.smn.utils.Utilities;

public class StartAgent {
	
	private Properties props;
	
	public StartAgent(String agentConfig) throws Exception {
		Utilities.log("Starting Agent for Self Managing Networks.....");
		
		initConfig(agentConfig);
		
		initServerSocket();
		
		initLocalServerSocket();
		
		checkImproperShutdown();
		
		Runtime.getRuntime().addShutdownHook(new ShutdownMonitor(props, agentConfig));
		
		Utilities.log("Agent for Self Managing Networks started.");
	}
	
	private void initServerSocket() {
		Utilities.log("Opening socket at : " + props.getProperty("agent_port"));
		
		Thread socketThread = new Thread() {
			@Override
			public void run() {
				try {
					ServerSocket serverSocket = new ServerSocket(Integer.parseInt(props.getProperty("agent_port")));
					while (true) {
						Socket socket = serverSocket.accept();
						Utilities.log("Accepted connection from " + socket.getRemoteSocketAddress());
						new MessageProcessor(socket).start();
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		};
		socketThread.start();
		
		Utilities.log("Socket opened at : " + props.getProperty("agent_port"));
	}
	
	private void initLocalServerSocket() {
		Utilities.log("Opening socket at : " + props.getProperty("agent_local_port"));
		
		Thread socketThread = new Thread() {
			@Override
			public void run() {
				try {
					ServerSocket serverSocket = new ServerSocket(Integer.parseInt(props.getProperty("agent_local_port")));
					while (true) {
						Socket socket = serverSocket.accept();
						Utilities.log("Accepted connection from " + socket.getRemoteSocketAddress());
						new FileCopier(socket, 
									props.getProperty("manager_ip"), Integer.parseInt(props.getProperty("manager_port")),
									props.getProperty("alt_manager_ip"), Integer.parseInt(props.getProperty("alt_manager_port"))).start();
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		};
		socketThread.start();
		
		Utilities.log("Socket opened at : " + props.getProperty("agent_local_port"));
	}
	
	private void checkImproperShutdown() throws Exception {
		if(props.getProperty("status").equals("Running")) {
			Utilities.log("Improper shutdown detected");
			Socket socket = new Socket(props.getProperty("manager_ip"), 
										Integer.parseInt(props.getProperty("manager_port")));
			OutputStream os = socket.getOutputStream();
			os.write(PDUFactory.createISTrapPDU());
		}
	}

	private void initConfig(String agentConfig) throws Exception {
		Utilities.log("Initializing agent with config : " + agentConfig);
		
		File agentConfigFile = new File(agentConfig);
		if (!agentConfigFile.exists()) {
			System.err.println("Agent config " + agentConfig + " does not exists");
			System.exit(1);
		}
	
		props = new Properties();
		props.loadFromXML(new FileInputStream(agentConfigFile));
		
		Utilities.log("Agent Initialized.");
	}

	public static void main(String[] args) throws Exception {
		if (args.length != 1) {
			usage();
			System.exit(1);
		}
		
		new StartAgent(args[0]);
	}
	
	private static void usage() {
		System.out.println("java -jar agent.jar <agent-config-xml>");
	}
}
